<?php

defined('BASEPATH') or die('forbidden');
/**
 * 框架基础辅助函数库
 * @author  Karson
 * @name    base.php
 * @since   2013-6-17 16:11:00
 */

/**
 * 自定义自动加载类函数
 * @param string $classname 类名称
 */
function autoload($classname) {
    $classname = strtolower($classname);
    $filename = APPPATH . 'libraries/' . $classname . '.php';
    if (!is_file($filename)) {
        $filename = BASEPATH . 'libraries/' . $classname . '.php';
        if (!is_file($filename)&&  stripos($filename, '/notice/PHPExcel/')<0)
            exit("加载的类[{$classname}]不存在");
    }
    include_once $filename;
}

/**
 * 获取指定配置文件值
 * @param string $item 配置项的名称
 * @return mixed 获取到的配置值
 */
function config_item($item) {
    static $config_item = array();
    if (!isset($config_item[$item])) {
        $config = & get_config();
        if (!isset($config[$item]))
            return false;
        $config_item[$item] = $config[$item];
    }
    return $config_item[$item];
}

/**
 * 调试输出
 * @return string 
 */
function dump() {
    $string = '';
    foreach (func_get_args() as $value) {
        $string .= '<pre>' . h($value === NULL ? 'NULL' : (is_scalar($value) ? $value : print_r($value, TRUE))) . "</pre>\n";
    }
    return $string;
}

/**
 * 获取生成一个uuid全球唯一标识
 * @return string
 */
function get_uuid() {
    return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
    );
}

function get_sessionid() {
    return str_replace("-", "", get_uuid());
}

/**
 * 自定义错误处理函数
 * @param constant $errorno 错误级别
 * @param string $message 错误信息
 * @param string $filepath 错误所在文件
 * @param int $line 错误所在行号
 * @return bool 错误返回false
 */
function errorhandler($errorno, $message, $filepath, $line) {
    if (error_reporting() === 0) {
        return false;
    }
    if (error_reporting() & $errorno) {
        //$error = & load_class('error');
        //$error->show_php_error($errorno, $message, $filepath, $line);
    }
}

/**
 * 自定义异常处理函数
 * @param object $exception 异常对象
 */
function exceptionhandler($exception) {
    show_error($exception->getMessage());
}

/**
 * 获取框架对象
 * @param string $tag 对象标识符，默认为default[框架对象]，可选controller[控制器对象]
 * @return object 框架对象
 */
function &get_instance($tag = 'default') {
    return framework::instance($tag);
}

/**
 * 读取配置文件
 * @staticvar var $main_conf 静态变量
 * @return array 获取到的指定的配置数组
 */
function &get_config() {
    static $main_conf;
    if (!isset($main_conf)) {
        $framework = &get_instance();
        $main_conf[0] = $framework->config;
    }
    return $main_conf[0];
}

/**
 * 初始化类对象
 * @param object $class_object 对象
 * @return object 类对象
 */
function &init_class(&$class_object) {
    return $class_object;
}

/**
 * 加载类并实例化
 * @staticvar var $objects 静态对象
 * @param string $class 类名称
 * @param mixed $params 传递参数值
 * @return object 成功返回对象
 */
function &load_class($class, $params = null) {
    static $objects = array();
    if (isset($objects[$class]))
        return $objects[$class];
    $name = ucfirst($class);
    if (is_null($params))
        $objects[$class] = & init_class(new $name());
    else
        $objects[$class] = & init_class(new $name($params));
    return $objects[$class];
}

/**
 * 获取网站入口所在的URL地址
 * @return string 获取的URL地址
 */
function base_url($full = false) {
    static $baseurl = null;
    if (is_null($baseurl)) {
        $config = & get_config();
        if ($config['base_url'] == '') {
            $config['base_url'] = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']));
            $config['base_url'] = trim($config['base_url'], '/');
            $config['base_url'] = empty($config['base_url']) ? '/' : "/{$config['base_url']}/";
        }
        $baseurl = $config['base_url'];
        $returnurl = $baseurl;
    } else {
        $returnurl = $baseurl;
    }
    if ($full) {
        $domain = isset($_SERVER['HTTP_HOST']) && stripos($_SERVER['HTTP_HOST'], ':') !== false ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
        $returnurl = 'http://' . $domain . $baseurl;
    }
    return $returnurl;
}

/**
 * 获取网站的URL地址或指定路径的URL
 * @param mixed $url 需要构造的URL基址
 * @return string 处理后的URL地址
 */
function site_url($url = '', $full = false) {
    $config = & get_config();
    $last = substr($url, -1);
    $baseurl = base_url($full);
    //去掉尾部/
    $baseurl = $config['url_rewrite'] ? $baseurl : $baseurl . $config['index_page'];
    if (is_array($url))
        $url = implode('/', $url);
    $url = trim($url, '/');
    if ($config['url_rewrite']) {
        $baseurl .= $url;
    } else {
        $baseurl .= '/' . $url;
    }
    return $baseurl .= $last == '/' ? '/' : '';
}

/**
 * 获取当前URL地址
 * @return string 当前URL地址
 */
function current_url($full = false) {
    $framework = &get_instance();
    return site_url($framework->path_info, $full);
}

/**
 * 获取当前控制器和方法操作的的URL
 * @return string
 */
function current_action() {
    $framework = &get_instance();
    return site_url($framework->controller_name . '/' . $framework->action);
}

/**
 * 获取元素URL指定分段位置值
 * @param int $index 分段的位置，位置从0算起，控制器为0，方法为1，依次类推
 * @param string $default 当未获取到指定位置值的时候的默认值，默认为空
 * @param string $slash 前后加上/，默认为空，可选值first(),final
 * @return string 成功返回指定位置值，失败返回default的值
 */
function segment($index, $default = '', $slash = '') {
    $index = $index <= 0 ? 0 : $index;
    $url = array_slice(explode('/', get_instance()->truepath_info), 1);
    if (isset($url[$index]) && $url[$index] != '')
        if ($slash == 'first' || $slash == 'forward' || $slash == 'before') {
            return '/' . $url[$index];
        } else if ($slash == 'final' || $slash == 'behind' || $slash == 'after') {
            return $url[$index] . '/';
        } else {
            return $url[$index];
        }
    else
        return $default;
}

/**
 * 记录日志信息
 * @param string $msg 日志信息
 * @param string $level 日志类型
 * @return bool 失败返回false
 */
function log_message($msg = '', $type = 'debug') {
    if ($type == 'debug')
        $log = config_item('debug_log');
    else if ($type == 'error')
        $log = config_item('error_log');
    else
        $log = true;
    if (!$log)
        return false;
    $filepath = APPPATH . "logs/{$type}-" . date('Y-m-d') . '.php';
    $message = '';
    if (!is_file($filepath))
        $message = "<" . "?php defined('BASEPATH') or die('forbidden'); ?" . ">\n\n" . $message;
    if (!$fp = @fopen($filepath, 'a'))
        return false;
    $message .= $type . ' --> ' . date('m-d H:i:s') . ' --> ' . $msg . "\n";
    flock($fp, LOCK_EX);
    fwrite($fp, $message);
    flock($fp, LOCK_UN);
    fclose($fp);
}

/**
 * 显示404错误
 * @param string $page 错误文件名称
 */
function show_404($page = '') {
    $framework = &get_instance('controller');
    $message = '页面未找到或已转移';
    $error = & load_class('error');
    $error->show_404($page);
    exit;
}

/**
 * 显示错误
 * @param string $message 错误数据
 */
function show_error($message, $code = 500, $title = '未知的错误信息') {
    $error = & load_class('error');
    echo $error->show_error($title, $message, 'error_general', $code);
    exit;
}

/**
 * 操作成功信息
 * @param string $msg 消息内容
 * @param string $url 跳转到的地址 -1为后退
 * @param int $time 跳转等待时间，单位为毫秒
 */
function success($msg, $url = '-1', $time = 2000) {
    show_message($msg, $url, $time, 'success');
}

/**
 * 操作失败信息
 * @param string $msg 消息内容
 * @param string $url 跳转到的地址 -1为后退
 * @param int $time 跳转等待时间，单位为毫秒
 */
function error($msg, $url = '-1', $time = 2000) {
    show_message($msg, $url, $time, 'error');
}

/**
 * 弹出窗口
 * @param string $msg 消息内容
 * @param string $url 跳转的地址 -1为后退
 */
function alert($msg, $url = '-1') {
    if ((string) $url == '-1') {
        $url = "history.go(-1);";
    } else {
        $url = "location.href='{$url}';";
    }
    echo "<script>alert('{$msg}');{$url}</script>";
}

/**
 * 提示消息
 * @param string $msg 消息内容
 * @param string $url 跳转到的地址 -1为后退
 * @param int $time 跳转等待时间，单位为毫秒
 * @param string $type 类型 success/error/help/fav/alert alert为弹出窗口(此时$time无效)
 */
function show_message($msg, $url = '-1', $time = 3000, $type = 'success') {
    $config = &get_instance()->config;
    //$time = ($time == 0) ? 3000 : $time;
    if ($url == '')
        $url = '-1';
    if ((string) $url == '-1')
        $url = "javascript:history.go(-1);";
    $htmlhead = "";
    if ($type == 'alert') {
        $message = "<script type='text/javascript'>alert(\"" . str_replace("\"", "“", $msg) . "\");location.href='{$url}'</script>";
        echo $message;
    } else {
        $image = $config['res_url'] . "/images/tips/" . $type . ".gif";
        $title = "温馨提示";
        $time = ceil($time / 1000);
        //同步需要执行的代码
        $script = isset($GLOBALS['ucsynlogin']) ? $GLOBALS['ucsynlogin'] : '';
        $script .= "<script type='text/javascript'>
                    function jump_url(){
                    remain = parseInt(document.getElementById('timeid').innerHTML);
                    if(remain > 1){
                        document.getElementById('timeid').innerHTML = remain-1;
                        setTimeout('jump_url()', 1000);
                    }else{
                        location.href = \"{$url}\";
                    }
               }";
        $script .= ( $url != 'javascript:;' && $url != '') ? "setTimeout('jump_url()', 1000);" : "";
        $script .= '</script>';
        include APPPATH . 'errors/show_message.php';
    }
    exit;
}

/**
 * 输出xml或json格式
 * @param array $data 输出的数据
 * @param array $attr 属性
 * @param string $root 根节点
 * @param string $item 列表节点
 * @param string $header 头部信息
 * @param string $encoding 编码信息
 */
function xml_encode($data, $attr = null, $root = "root", $item = 'item', $header = '', $encoding = 'utf-8') {
    $format = isset($_GET['format']) ? $_GET['format'] : 'xml';
    $framework = &get_instance('controller');
    if (function_exists("check_login")) {
        //记录调试信息开始
        $get = $post = '';
        $method = 'get';
        if (is_submit()) {
            $t = array();
            foreach ($_POST as $m => $n) {
                $t[] = "{$m}={$n}";
            }
            $post = implode('&', $t);
            $method = 'post';
        }
        $t = array();
        foreach ($_GET as $m => $n) {
            $t[] = "{$m}={$n}";
        }
        $get = implode('&', $t);
        $debug = array(
            'is_logined' => check_login(),
            'user_id' => $framework->auth->user_id,
            'username' => $framework->auth->username,
            'requesturl' => get_instance()->path_info,
            'requestmethod' => $method,
            'postdata' => $post,
            'getdata' => $get,
            'usedmemories' => used_memeory(),
            'sqlqueries' => $framework->db->querycounts,
            'executetime' => used_microtime(),
        );
    } else {
        $debug = array();
    }
    if (is_array($attr)) {
        $attr = array_merge($attr, $debug);
    } else {
        $attr = $attr == null ? $debug : '';
    }
    if ($format == 'temp') {
        header("Content-Type: application/json; charset=utf-8");
        echo json_encode($data);
        exit;
    } else if ($format == 'json') {
        header("Content-Type: application/json; charset=utf-8");
        if (isset($data['code']) && isset($data['result'])) {
            echo json_encode($data);
        } else {
            $attr['list'] = $data;
            echo json_encode($attr);
        }
        exit;
    }
    //记录调试信息结束
    if (is_array($attr)) {
        $t = array();
        foreach ($attr as $m => $n) {
            $t[] = ' ' . $m . '="' . $n . '"';
        }
        $attr = implode('', $t);
    } else {
        $attr = '';
    }
    $xml = '<?xml version="1.0" encoding="' . $encoding . '"?>';
    $xml.= $header ? "\n" . $header : '';
    $xml.= "\n" . '<' . $root . $attr . '>';
    $xml.= data_to_xml($data, 0, $item);
    $xml.= "\n" . '</' . $root . '>';
    unset($data, $attr);
    echo $xml;
    exit;
}

function data_to_xml($data, $level = 0, $item = 'item') {
    $level++;
    if (is_object($data)) {
        $data = get_object_vars($data);
    }
    $xml = '';
    foreach ($data as $key => $val) {
        is_numeric($key) && $key = $item;
        $xml .= "\n" . str_repeat("\t", $level) . '<' . $key . '>';
        $xml .= ( is_array($val) || is_object($val)) ? data_to_xml($val, $level, $item) . "\n" . str_repeat("\t", $level) : xml_replace($val);
        list($key, ) = explode(' ', $key);
        $xml .= '</' . $key . '>';
    }
    unset($data);
    return $xml;
}

function xml_replace($data) {
    if (is_numeric($data))
        return $data;
    return str_replace(array("<", ">", "&", "'", "\""), array("&lt;", "&gt;", "&amp;", "&apos;", "&quot;"), $data);
}

/**
 * 输出XML数据
 * @param int $code 代码
 * @param string $result 结果
 * @param array $attr
 */
function xml_output($code = 0, $result = '', $attr = null) {
    $data = array('code' => $code, 'result' => $result);
    echo xml_encode($data, $attr);
    exit;
}

/**
 * JSON格式输出
 * @param int $code
 * @param mixed $result 
 */
function json_output($code = 0, $result = '') {
    echo json_encode(array('code' => $code, 'result' => $result));
    exit;
}

/**
 * JSON输出不编码中文字符
 * @param mixed $data
 * @return str
 */
function json_encode_adv($data) {
    //return preg_replace("#\\\u([0-9a-f]{4})#ie", "mb_convert_encoding(pack('H4', '\\1'), 'UTF-8', 'UCS-2')", json_encode($data));
    return preg_replace("#\\\u([0-9a-f]{4})#ie", "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))", json_encode($data));
}

/**
 * 读取时区偏移秒数
 * @return int
 */
function get_timezone_offset($name) {
    $timezone = new DateTimeZone($name);
    return $timezone->getOffset(new DateTime("now", $timezone));
}

/**
 * 读取时区列表
 * @return array
 */
function get_timezone_list() {
    $list = array();
    foreach (DateTimeZone::listIdentifiers() as $m => $n) {
        $list[$n] = $n;
    }
    return $list;
}

/**
 * 不影响HTML结构调试输出
 * @param string $str
 */
function d($str = '') {
    echo "<!--" . memory_get_usage() . ",{$str}," . (microtime(true) - START_TIME) . "-->\n";
}

/**
 * 程序崩溃了
 */
function shutdown() {
    //xhprof调试开始
    if (defined('XHPROF_DEBUG')) {
        defined('XHPROF_ROOT') or define('XHPROF_ROOT', 'D:\Wamp\apps');

        $xhprofData = xhprof_disable();
        include_once(XHPROF_ROOT . '/xhprof_lib/utils/xhprof_lib.php');
        include_once(XHPROF_ROOT . '/xhprof_lib/utils/xhprof_runs.php');

        $xhprofRuns = new XHProfRuns_Default();
        $runid = $xhprofRuns->save_run($xhprofData, 'sanguo');
        echo "<!--http://localhost/xhprof/index.php?run={$runid}&source=sanguo-->";
    }
    //xhprof调试结束
    if ($e = error_get_last()) {
        //严重错误提示
        $error = & load_class('error');
        $error->show_php_error($e['type'], $e['message'], $e['file'], $e['line'], 'error_php');
    }
}

/**
 * 获取输出语言,同sprintf(gettext('hello %s'),'word')
 * @return string 
 */
function translate() {
    $args = func_get_args();
    $num = func_num_args();
    //var_dump($args);
    //echo "num".$num;
    //var_dump($GLOBALS['lang']);
    if (!isset($GLOBALS['lang'][$args[0]]))
    {
        debug($args[0]);
    }
    $args[0] = isset($GLOBALS['lang'][$args[0]]) ? $GLOBALS['lang'][$args[0]] : (isset($args[0]) ? $args[0] : '');
    if ($num <= 1)
    {
        return $args[0];
    }
    return call_user_func_array('sprintf', $args);
}

if (isset($_GET['debug'])) {
//    xhprof_enable(XHPROF_FLAGS_MEMORY);
//    define('XHPROF_DEBUG', true);
}
define('DATAPATH', APPPATH . 'datas/');
define('ERRORPATH', APPPATH . 'errors/');
define('LOGPATH', APPPATH . 'logs/');
define('VIEWPATH', APPPATH . 'views/');
define('UPLOADPATH', dirname(BASEPATH) . '/uploads/');
//define('CONFIGPATH', dirname(BASEPATH) . '/application/configs/');

//自动加载类,PHP5 ONLY
spl_autoload_register('autoload');

//自定义错误和异常处理
set_error_handler('errorhandler');
set_exception_handler('exceptionhandler');
register_shutdown_function('shutdown');